home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / jwpsrc.zip / MEMORY.C < prev    next >
C/C++ Source or Header  |  1993-03-31  |  11KB  |  481 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5. #define MAGIC           0x42022667L
  6.  
  7. typedef struct MemoryStruct {
  8.     long int magic;
  9.     void far *page;
  10.     unsigned int size;
  11.     BOOL allocated;
  12.     struct MemoryStruct far *next, far *prev;
  13. } MEMHEADER;
  14.  
  15. typedef struct PageHeaderStruct {
  16.     long int magic;
  17.     HANDLE handle;
  18.     unsigned int size;
  19.     unsigned int used;
  20.     unsigned int overhead;
  21.     MEMHEADER far *data, far *empty;
  22.     struct PageHeaderStruct far *next, far *prev;
  23. } MEMPAGEHEADER;
  24.  
  25. typedef struct {
  26.     MEMPAGEHEADER far *pages;
  27.     int nr_pages;
  28. } MAINMEMHEADER;
  29.  
  30. #define PAGESIZE        (4 * 1024)
  31. #define USEABLESIZE     (PAGESIZE - sizeof(MEMPAGEHEADER) - sizeof(MEMHEADER))
  32.  
  33.  
  34. static MAINMEMHEADER header = { NULL, 0 };
  35. static BOOL NoErrors = FALSE;
  36.  
  37.  
  38.  
  39. void EnableNullPointers (BOOL enable)
  40. {
  41.     NoErrors = enable;
  42. }
  43.  
  44.  
  45. /* Make room by trimming off undo's */
  46.  
  47. static BOOL MakeRoom (void)
  48. {
  49.     FILEOPTIONS *f, *f1;
  50.     UNDOBUF far *up;
  51.     int largest;
  52.     void far *ptr;
  53.  
  54.  
  55.     largest = -1;
  56.  
  57.     for (f = fileoptions; f != NULL; f = f->next) {
  58.         if (f->undo != NULL && f->undolevels > largest) {
  59.             largest = f->undolevels;
  60.             f1 = f;
  61.         }
  62.     }
  63.  
  64.     if (largest < 0) return (FALSE);
  65.  
  66.  
  67.     /* Start trimming */
  68.  
  69.     up = f1->undotail->prev;
  70.     FreeUndo(f1->undotail);
  71.  
  72.     f1->undolevels--;
  73.     if (up != NULL) up->next = NULL;
  74.  
  75.     if (up == NULL) {
  76.         f1->undo = f1->undotail = NULL;
  77.         f1->undolevels = 0;
  78.     }
  79.  
  80.     return (TRUE);
  81. }
  82.  
  83.  
  84.  
  85. static MEMPAGEHEADER far *AddPage(unsigned int n)
  86. {
  87.     void far *cp;
  88.     MEMHEADER far *mp;
  89.     MEMPAGEHEADER far *p;
  90.     HANDLE handle = NULL;
  91.  
  92.     handle = GlobalAlloc(GHND, n);
  93.     if (handle == NULL) return (NULL);
  94.  
  95.     if (header.pages == NULL || header.nr_pages <= 0) {
  96.         p = header.pages = (MEMPAGEHEADER far *) GlobalLock(handle);
  97.         p->prev = NULL;
  98.     } else {
  99.         for (p = header.pages; p->next != NULL; p = p->next);
  100.         p->next = (MEMPAGEHEADER far *) GlobalLock(handle);
  101.         p->next->prev = p;
  102.         p = p->next;
  103.     }
  104.  
  105.     p->magic = MAGIC;
  106.     p->handle = handle;
  107.     p->next = NULL;
  108.     p->size = n;
  109.     p->used = 0;
  110.     p->overhead = sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER);
  111.  
  112.     cp = ((char far *) p) + sizeof(MEMPAGEHEADER);
  113.     mp = (MEMHEADER far *) cp;
  114.  
  115.     p->data = p->empty = mp;
  116.  
  117.     mp->magic = 0L;
  118.     mp->allocated = FALSE;
  119.     mp->page = p;
  120.     mp->size = p->size - p->overhead;
  121.     mp->next = mp->prev = NULL;
  122.  
  123.     header.nr_pages++;
  124.  
  125.     return (p);
  126. }
  127.  
  128.  
  129.  
  130. static void DeletePage (MEMPAGEHEADER far *p)
  131. {
  132.     if (p->next == NULL && p->prev == NULL) {
  133.         header.pages = NULL;
  134.         header.nr_pages = 0;
  135.         if (GlobalUnlock(p->handle) || GlobalFree(p->handle) != NULL) {
  136.             ErrorMessage(global.hwnd, "Cannot free memory page 0x%x!", p->handle);
  137.         }
  138.     } else {
  139.         if (p == header.pages) header.pages = p->next;
  140.         header.nr_pages--;
  141.  
  142.         if (p->prev != NULL) p->prev->next = p->next;
  143.         if (p->next != NULL) p->next->prev = p->prev;
  144.  
  145.         if (GlobalUnlock(p->handle) || GlobalFree(p->handle) != NULL) {
  146.             ErrorMessage(global.hwnd, "Cannot free memory page 0x%x!", p->handle);
  147.         }
  148.     }
  149. }
  150.  
  151.  
  152.  
  153. void far *SegHeapAlloc (unsigned int n)
  154. {
  155.     MEMPAGEHEADER far *p = NULL;
  156.     MEMHEADER far *mp;
  157.     char far *cp;
  158.  
  159.     if (n >= 65535) {
  160.         ErrorMessage(global.hwnd, "SegHeapAlloc: size (%u) > 64K!\n\n"
  161.                                   "The program is not stable.  You should save your work NOW!",
  162.                                   n);
  163.         n = C64K;
  164.     }
  165.  
  166.     /* Larger than page size? */
  167.  
  168.     if (n > USEABLESIZE) {
  169.         for (;;) {
  170.             p = AddPage(n + sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER));
  171.  
  172.             if (p != NULL) break;
  173.  
  174.             if (NoErrors) return (NULL);
  175.             if (MakeRoom()) continue;
  176.             if (!RetryMessage("Out of Global Memory:\nAllocating %u bytes", n))
  177.                 return (NULL);
  178.         }
  179.  
  180.         mp = p->data;
  181.         mp->magic = MAGIC;
  182.         mp->allocated = TRUE;
  183.  
  184.         mp->next = mp->prev = NULL;
  185.  
  186.         p->used = n;
  187.         p->empty = NULL;
  188.  
  189.         cp = ((char far *) mp) + sizeof(MEMHEADER);
  190.         _fmemset(cp, 0, n);
  191.  
  192.         return ((void far *) cp);
  193.     }
  194.  
  195.  
  196. LookForHole:
  197.  
  198.     /* Search for the hole */
  199.  
  200.     for (p = header.pages; p != NULL; p = p->next) {
  201.         /* Scan the chains */
  202.         if (p->size - p->used - p->overhead <= 0) continue;
  203.         if (p->empty == NULL) continue;
  204.  
  205.         for (mp = p->empty; mp != NULL; mp = mp->next) {
  206.             if (!mp->allocated && mp->size >= n) break;
  207.         }
  208.  
  209.         if (mp != NULL) break;
  210.     }
  211.  
  212.     /* New page needed? */
  213.  
  214.     if (p == NULL) {
  215.         for (;;) {
  216.             p = AddPage(PAGESIZE);
  217.  
  218.             if (p != NULL) break;
  219.  
  220.             if (NoErrors) return (NULL);
  221.             if (MakeRoom()) goto LookForHole;
  222.             if (!RetryMessage("Out of Global Memory:\nAllocating %u bytes", n))
  223.                 return (NULL);
  224.         }
  225.  
  226.         mp = p->data;
  227.     }
  228.  
  229.     /* Do we need to break it up? */
  230.  
  231.     if (mp->size - n > sizeof(MEMHEADER)) {
  232.         MEMHEADER far *mp2;
  233.  
  234.         cp = ((char far *) mp) + n + sizeof(MEMHEADER);
  235.         mp2 = (MEMHEADER far *) cp;
  236.  
  237.         mp2->magic = 0L;
  238.         mp2->allocated = FALSE;
  239.         mp2->page = p;
  240.         mp2->size = mp->size - n - sizeof(MEMHEADER);
  241.  
  242.         mp2->next = mp->next;
  243.         mp2->prev = mp;
  244.         if (mp->next != NULL) mp->next->prev = mp2;
  245.         mp->next = mp2;
  246.  
  247.  
  248.         p->overhead += sizeof(MEMHEADER);
  249.  
  250.         mp->size = n;
  251.     }
  252.  
  253.     mp->magic = MAGIC;
  254.     mp->allocated = TRUE;
  255.  
  256.     p->used += n;
  257.     cp = ((char far *) mp) + sizeof(MEMHEADER);
  258.  
  259.     /* Search for the next empty hole */
  260.  
  261.     for (; mp != NULL; mp = mp->next) {
  262.         if (!mp->allocated && mp->size > 0) break;
  263.     }
  264.  
  265.     p->empty = mp;
  266.  
  267.     _fmemset(cp, 0, n);
  268.  
  269.     return ((void far *) cp);
  270. }
  271.  
  272.  
  273. void SegHeapFree (void far *vp)
  274. {
  275.     MEMPAGEHEADER far *p;
  276.     MEMHEADER far *mp, far *mp2;
  277.     char far *cp;
  278.  
  279.     cp = ((char far *) vp) - sizeof(MEMHEADER);
  280.     mp = (MEMHEADER far *) cp;
  281.  
  282.     if (mp->magic != MAGIC || !mp->allocated) {
  283.         ErrorMessage(global.hwnd, "Trying to deallocate invalid memory block [%Fp, %u byte%s]!\n\n"
  284.                                   "The program is not stable.  You should save your work NOW!",
  285.                         vp, mp->size, (mp->size > 1) ? "s" : "");
  286.         return;
  287.     }
  288.  
  289.     p = (MEMPAGEHEADER far *) mp->page;
  290.     p->used -= mp->size;
  291.  
  292.     mp->magic = 0L;
  293.     mp->allocated = FALSE;
  294.  
  295.     /* Merge? */
  296.  
  297.     mp2 = mp->prev;
  298.  
  299.     if (mp2 != NULL && !mp2->allocated) {
  300.         mp2->next = mp->next;
  301.         if (mp->next != NULL) mp->next->prev = mp2;
  302.         mp2->size += mp->size + sizeof(MEMHEADER);
  303.  
  304.         p->overhead -= sizeof(MEMHEADER);
  305.  
  306.         mp = mp2;
  307.     }
  308.  
  309.     mp2 = mp->next;
  310.  
  311.     if (mp2 != NULL && !mp2->allocated) {
  312.         mp->next = mp2->next;
  313.         if (mp2->next != NULL) mp2->next->prev = mp;
  314.  
  315.         mp->size += mp2->size + sizeof(MEMHEADER);
  316.  
  317.         p->overhead -= sizeof(MEMHEADER);
  318.     }
  319.  
  320.     if (mp->prev == NULL && mp->next == NULL) {
  321.         DeletePage(p);
  322.     } else {
  323.         if (p->empty == NULL || mp < p->empty) p->empty = mp;
  324.     }
  325. }
  326.  
  327.  
  328.  
  329. void far *SegHeapRealloc (void far *p, unsigned int n)
  330. {
  331.     MEMHEADER far *mp;
  332.     char far *cp;
  333.  
  334.     /* Block already large enough? */
  335.  
  336.     cp = ((char far *) p) - sizeof(MEMHEADER);
  337.     mp = (MEMHEADER far *) cp;
  338.  
  339.     if (mp->magic != MAGIC) {
  340.         ErrorMessage(global.hwnd, "Trying to reallocate invalid memory block [%Fp, %u byte%s]!\n\n"
  341.                                   "The program is not stable.  You should save your work NOW!",
  342.                         p, mp->size, (mp->size > 1) ? "s" : "");
  343.  
  344.         /* Minimize the damage */
  345.  
  346.         cp = SegHeapAlloc(n);
  347.         if (cp == NULL) return (NULL);
  348.         _fmemcpy(cp, p, (mp->size >= n) ? n : mp->size);
  349.         return (cp);
  350.     }
  351.  
  352.     if (mp->size >